import db from '../utils/db';
import gamemgr_xlch from './gamemgr_xlch';
import gamemgr_xzdd from './gamemgr_xzdd';

let rooms:{[key:string]: roomInfo} = {};
let creatingRooms = {};
let userLocation: { [key: string]: seat }  = {};
let totalRooms = 0;
const DI_FEN = [1, 2, 5];
const MAX_FEN = [3, 4, 5];
const JU_SHU = [4, 8];
const JU_SHU_COST = [2, 3];



function generateRoomId(){
    let roomId = '';
    for(let i = 0; i < 6; i++){
        roomId += Math.floor(Math.random() * 10);
    }
    return roomId;
}


function constructRoomFromDb(dbdata: dbdata){
    const roomInfo: roomInfo = {
        uuid: dbdata.uuid,
        id: dbdata.id,
        numOfGames: dbdata.num_of_turns,
        createTime: dbdata.create_time,
        nextButton: dbdata.next_button,
        seats: new Array(4),
        conf: JSON.parse(dbdata.base_info),
    };

    if(roomInfo.conf.type == 'xlch'){
        roomInfo.gameMgr = gamemgr_xlch;
    }
    else{
        roomInfo.gameMgr = gamemgr_xzdd;
    }

    const roomId = roomInfo.id;
    for(let i = 0; i < 4; i++){
        let s = roomInfo.seats[i] = <seat>{};
        s.userId = dbdata['user_id' + i];
        s.score = dbdata['user_score' + i];
        s.name = dbdata['user_name' + i];
        s.ready = false;
        s.seatIndex = i;
        s.numZiMo = 0;
        s.numJiePao = 0;
        s.numDianPao = 0;
        s.numAnGang = 0;
        s.numMingGang = 0;
        s.numChaJiao = 0;

        if(s.userId > 0){
            userLocation[s.userId] = {
                roomId: roomId,
                seatIndex: i,
            };
        }

        rooms[roomId] = roomInfo;
        totalRooms++;
        return roomInfo;
    }
}



export default class Roommgr{
    
    static getTotalRooms(){
        return totalRooms;
    }

    static createRoom(creator, roomConf: conf, gems, ip, port, callback){

        if(
            roomConf.type == null ||
            roomConf.difen == null ||
            roomConf.zimo == null ||
            roomConf.jiangdui == null ||
            roomConf.huansanzhang == null ||
            roomConf.zuidafanshu == null ||
            roomConf.jushuxuanze == null ||
            roomConf.dianganghua == null ||
            roomConf.menqing == null ||
            roomConf.tiandihu == null
        ){
            callback(1, null);
            return;
        }

        if(roomConf.difen < 0 || roomConf.difen > DI_FEN.length){
            callback(1, null);
            return;
        }
        
        if(roomConf.zimo < 0 || roomConf.zimo > 2){
            callback(1, null);
            return;
        }

        if(roomConf.zuidafanshu < 0 || roomConf.zuidafanshu > MAX_FEN.length){
            callback(1, null);
            return;
        }
        
        if(roomConf.jushuxuanze < 0 || roomConf.jushuxuanze > JU_SHU.length){
            callback(1, null);
            return;
        }

        const cost = JU_SHU_COST[roomConf.jushuxuanze];
        if(cost > gems){
            callback(2222, null);
            return;
        }

        const fnCreate = () => {

            const roomId = generateRoomId();
            if(rooms[roomId] != null || creatingRooms[roomId] != null){
                fnCreate();
            }
            else{
                creatingRooms[roomId] = true;

                db.is_room_exist(roomId, ret => {

                    if(ret){
                        delete creatingRooms[roomId];
                        fnCreate();
                    }
                    else{
                        const createTime = Math.ceil(Date.now() / 1000);
                        const roomInfo: roomInfo = {
                            uuid: '',
                            id: roomId,
                            numOfGames: 0,
                            createTime: createTime,
                            nextButton: 0,
                            seats: [],
                            conf: {
                                type: roomConf.type,
                                baseScore: DI_FEN[roomConf.difen],
                                zimo: roomConf.zimo,
                                jiangdui: roomConf.jiangdui,
                                hsz: roomConf.huansanzhang,
                                dianganghua: roomConf.dianganghua,
                                menqing: roomConf.menqing,
                                tiandihu: roomConf.tiandihu,
                                maxFan: MAX_FEN[roomConf.zuidafanshu],
                                maxGames: JU_SHU[roomConf.jushuxuanze],
                                creator: creator,
                            }
                        };

                        if(roomConf.type == 'xlch'){
                            roomInfo.gameMgr = gamemgr_xlch;
                        }
                        else{
                            roomInfo.gameMgr = gamemgr_xzdd;
                        }

                        for(let i = 0; i < 4; i++){
                            roomInfo.seats.push({
                                userId: 0,
                                score: 0,
                                name: '',
                                ready: false,
                                seatIndex: i,
                                numZiMo: 0,
                                numJiePao: 0,
                                numDianPao: 0,
                                numAnGang: 0,
                                numMingGang: 0,
                                numChaJiao: 0,
                            });
                        }

                        //写入数据库
                        const conf = roomInfo.conf;
                        db.create_room(roomInfo.id, roomInfo.conf, ip, port, createTime, (uuid) => {
                            delete creatingRooms[roomId];
                            if(uuid != null){
                                roomInfo.uuid = uuid;
                                rooms[roomId] = roomInfo;
                                totalRooms++;
                                callback(0, roomId);
                            }
                            else{
                                callback(3, null);
                            }
                        });
                    }
                });
            }

        };

        fnCreate();
    }

    static enterRoom(roomId, userId, userName, callback){
        const fnTakeSeat = (room: roomInfo) => {
            if(this.getUserRoom(userId) == roomId){
                //已存在
                return 0;
            }

            for(let i = 0; i < 4; i++){
                let seat = room.seats[i];
                if(seat.userId <= 0){
                    seat.userId = userId;
                    seat.name = userName;
                    userLocation[userId] = {
                        roomId: roomId,
                        seatIndex: i,
                    };
                    db.update_seat_info(roomId, i, seat.userId, '', seat.name);
                    //正常
                    return 0;
                }
            }
            //房间已满
            return 1;
        };

        let room = rooms[roomId];
        if(room){
            let ret = fnTakeSeat(room);
            callback(ret);
        }
        else{
            db.get_room_data(roomId, (dbdata) => {
                if(dbdata == null){
                    callback(2);
                }
                else{
                    room = constructRoomFromDb(dbdata);
                    const ret = fnTakeSeat(room);
                    callback(ret);
                }
            });
        }
    }


    static getUserRoom(userId){
        const location = userLocation[userId];
        if(location != null){
            return location.roomId;
        }
        return null;
    }

    static getRoom(roomId){
        return rooms[roomId];
    }

    static getUserSeat(userId){
        const location = userLocation[userId];
        if(location != null){
            return location.seatIndex;
        }
        return null;
    }

    static setReady(userId, value){

        const roomId = this.getUserRoom(userId);
        if(roomId == null){
            return;
        }

        const room = this.getRoom(roomId);
        if(room == null){
            return;
        }

        const seatIndex = this.getUserSeat(userId);
        if(seatIndex == null){
            return;
        }

        const s = room.seats[seatIndex];
        s.ready = value;
    }
}